<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <title>Vue3 Hello World 快速启动</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.0-beta.7/vue.global.js"></script>

</head>
<body>
<!--vue 应用实例挂载到此ID上，这样它及其下面的标签才能使用 vue 语法获取数据-->
<!--双大括号和 v-text 指令都是取值进行填充, v-text 取值后会对标签的内容进行替换-->
<div id="rootApp" style="margin: 50px;font-size: 18px">

    <p>{{msg}}</p>

    <h3>v-on 监听事件</h3>
    <hr/>
    <p>
        用法：v-on:事件名="JS片段或函数名" 简写 @事件名="JS片段或函数名"，如 v-on:click="methodName" 或 @click="handler"<br>
        1、v-on 用于注册JS事件，click 表示参数，是监听的事件名，如单击、双击、焦点等等;<br>
        2、事件处理器的值可以是：<br>
    <ul>
        <li>内联事件处理器：事件被触发时执行的内联 JavaScript 语句 (与 onclick 类似)。</li>
        <li>方法事件处理器：一个指向组件上定义的方法的属性名或是路径。</li>
    </ul>

    </p>
    距离过年还有 {{year_end_day}} 天。<br>
    <!--内联事件处理器通常用于简单场景-->
    <button type="button" v-on:click="year_end_day++">增加</button>
    <!--随着事件处理器的逻辑变得愈发复杂，内联代码方式变得不够灵活。因此 v-on 也可以接受一个方法名或对某个方法的调用-->
    <!--有时我们需要在内联事件处理器中访问原生 DOM 事件。你可以向该处理器方法传入一个特殊的 $event 变量-->
    <button type="button" v-on:click="clickYearEndDay('蚩尤后裔', $event)">减少</button>
    <br>
    <br>

    <h4>事件修饰符</h4>
    <a target="_blank" href="https://cn.vuejs.org/guide/essentials/event-handling.html#event-modifiers">官网</a>
    <p>
        在处理事件时调用 event.preventDefault() 或 event.stopPropagation() 是很常见的。尽管我们可以直接在方法内调用，<br/>
        但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。<br/>
        为解决这一问题，Vue 为 v-on 提供了事件修饰符。修饰符是用 . 表示的指令后缀，包含以下这些：<br/>
    <ul>
        <li>.stop</li>
        <li>.prevent</li>
        <li>.self</li>
        <li>.capture</li>
        <li>.once</li>
        <li>.passive</li>
    </ul>
    </p>
    <!--'v-' 前缀作为一种视觉提示，用来识别模板中 Vue 特定的 attribute，-->
    <!--然而对于一些频繁用到的指令来说，就会感到使用繁琐，v- 前缀也变得没那么重要了，-->
    <!--因此 Vue 为 v-bind 和 v-on 这两个最常用的指令，提供了特定简写：v-bind:xxx 可以省略 v-bind；v-on:xxx 可以省略 v-on，同时将 ':' 替换为 '@'-->
    <a href="" @click.prevent="clickYearEndDay()" style="color: green">学习 Vue 的第 {{count}} 天</a>

    <!--同样地，可以使用动态参数为一个动态的事件名绑定处理函数-->
    <!--<a v-on:[eventName]="doSomething()"> ... </a>-->


    <h3>按键修饰符</h3>
    <a target="_blank" href="https://cn.vuejs.org/guide/essentials/event-handling.html#key-modifiers">官网</a><br/><br/>
    <p>
        1、在监听键盘事件时，经常需要检查特定的按键。Vue 允许在 v-on 或 @ 监听按键事件时添加按键修饰符。<br/>
        2、可以直接使用 KeyboardEvent.key 暴露的按键名称作为修饰符，但需要转为 kebab-case 形式，如 page-down、page-up。<br/>
        3、Vue 为一些常用的按键提供了别名：<br/>
    <ul>
        <li>.enter</li>
        <li>.tab</li>
        <li>.delete (捕获“Delete”和“Backspace”两个按键)</li>
        <li>.esc</li>
        <li>.space</li>
        <li>.up</li>
        <li>.down</li>
        <li>.left</li>
        <li>.right</li>
    </ul>
    4、可以使用以下系统按键修饰符来触发鼠标或键盘事件监听器，只有当按键被按下时才会触发：<br/>
    <ul>
        <li>.ctrl</li>
        <li>.alt</li>
        <li>.shift</li>
        <li>.meta（meta 是 Command 键 (⌘)。在 Windows 键盘上，meta 键是 Windows 键）</li>
    </ul>
    5、鼠标按键修饰符：<br/>
    <ul>
        <li>.left</li>
        <li>.right</li>
        <li>.middle</li>
    </ul>
    </p>
    <!-- 仅在 `key` 为 `Enter` 时调用 `submit` -->
    修改意见(回车提交)：<input type="text" @keyup.enter="enterFun()" @click="is_submit=null"/>&nbsp;&nbsp;
    <button type="button" @keyup.enter="enterFun()">回车提交</button>
    <span>{{is_submit}}</span>


</div>

</body>

<script type="text/javascript">
    let count = 1;
    let is_submit = "";

    // 1、每个 Vue 应用都是通过用 createApp 函数创建一个新的应用实例开始, 用来在应用中注册"全局"组件
    // 2、传递给 createApp 的选项用于配置根组件
    // 3、应用实例暴露的大多数方法都会返回该同一实例，方便链式编程
    const App = Vue.createApp({
        //组件选项
        // data 定义数据, html 中可以进行获取
        data() {
            // event 是 DOM 原生事件
            function clickYearEndDay(msg, event) {
                // this 指向组件实例(vm), 单纯的 count++ 是不会改变 html 中的数据的
                this.count++;
                this.msg = msg;
                if (this.year_end_day > 0) {
                    this.year_end_day--;
                }
                // event 是 DOM 原生事件
                if (event) {
                    console.log(event.target.tagName);
                }
            }

            function enterFun() {
                this.is_submit = "提交成功！";
            }

            return {
                msg: 'Hello Vue!',
                count,
                year_end_day: 100,
                is_submit,
                clickYearEndDay, //自定义的事件函数同样需要进行返回
                enterFun
            }
        },
    });

    // 4、一个应用需要被挂载(mount)到一个 DOM 元素中，当挂载(mount)应用时，该组件被用作渲染的起点
    // 5、与大多数应用方法不同的是 mount 不返回应用本身，而是返回的根组件实例(vm)
    const rootViewModel = App.mount("#rootApp");

    // 在 data 中定义的 property(属性) 是通过组件实例暴露的
    // 还有各种其他的组件选项，可以将用户定义的 property 添加到组件实例中，例如 methods，props，computed，inject 和 setup
    // 组件实例的所有 property 无论如何定义，都可以在组件的模板中访问
    // Vue 还通过组件实例暴露了一些内置 property，如 $attrs 和 $emit(都有一个 $ 前缀,以避免与用户定义的 property 名冲突)
    console.log(rootViewModel.msg);

    // 6、大多数的真实应用都会被组织成一个嵌套的、可重用的组件树，比如一个 todo 应用组件树：
    // Root Component
    // └─ TodoList
    //    ├─ TodoItem
    //    │  ├─ DeleteTodoButton
    //    │  └─ EditTodoButton
    //    └─ TodoListFooter
    //       ├─ ClearTodosButton
    //       └─ TodoListStatistics
    // 7、每个组件将有自己的组件实例 vm，对于一些组件，如 TodoItem，在任何时候都可能有多个实例渲染。
    // 这个应用中的所有组件实例将共享同一个应用实例
    // 根组件与其他组件没什么不同，配置选项是一样的，所对应的组件实例行为也是一样的


</script>
</html>
